<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 发布订阅包含三大功能，包括监听事件、触发事件和取消监听事件
      const emitter = {
        map: new Map(),
        $on(name, fn) {
          //this指向emitter对象
          this.map.get(name) || this.map.set(name, []);
          this.map.get(name).push(fn);
        },
        $emit(name, ...params) {
          console.log(this.map);
          let p = this.map.get(name);
          if (!p) throw new Error("没有该方法名");
          p.forEach((element) => {
            element(...params);
          });
        },
        // 删除一个函数
        // $off(name, fn) {
        //   let p = this.map.get(name);
        //   if (!p) throw new Error("没有该方法名");
        //   const index = p.indexOf(fn);
        //   if (index < 0) {
        //     return;
        //   }
        //   p.splice(index, 1);
        // },
        // 删除全部函数
        $off(name) {
          let p = this.map.get(name);
          if (!p) throw new Error("没有该方法名");
          this.map.delete(name);
        },
      };
      function fn(...e) {
        console.log("汪", ...e);
      }
      emitter.$on("spark", fn);
      emitter.$off("spark");
      emitter.$emit("spark", 1, 2);
    </script>
  </body>
</html>
